package #{packageName}.common.aop;

import #{packageName}.common.config.RedisKeyConfig;
import #{packageName}.common.template.RedisTemplate;
import #{packageName}.common.exception.ErrorCode;
import #{packageName}.common.exception.MyBizException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

/**
 * 鉴权用户登录
 */
@Component
@Aspect
public class AuthLoginAop {
    private static final Logger logger = LoggerFactory.getLogger(AuthLoginAop.class);
    private static final String HEAD_TOKEN = "token";
    @Autowired
    private RedisKeyConfig redisKeyConfig;
    @Autowired
    private RedisTemplate redisTemplate;

    // 定义一个 Pointcut, 使用 切点表达式函数 来描述对哪些 Join point 使用 advise.
    //切面 拦截所有接口鉴权 排除登录接口
    //@Pointcut("@annotation(#{packageName}.common.aop.AuthChecker)")
    @Pointcut("execution(public * #{packageName}.controller.*.*(..))")
    public void pointcut() {
    }

    // 定义 advise
    @Around("pointcut()")
    public Object checkAuth(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();


        // 检查用户所传递的 token 是否合法
        String token = getUserToken(request);
        if (ObjectUtils.isEmpty(token)) {
            throw new MyBizException(ErrorCode.BIZ_ERROR_USER_TOKEN_NULL.value(), ErrorCode.BIZ_ERROR_USER_TOKEN_NULL.msg());
        }

        if ("skip".equals(token) && isDebug()) {
            //TODO debug下直接通过
            return joinPoint.proceed();
        }

        //验证token
        String redisToken = redisTemplate.get(token);
        if (ObjectUtils.isEmpty(redisToken)) {
            logger.error("token is not login");
            throw new MyBizException(ErrorCode.BIZ_ERROR_USER_NOT_LOGIN.value(), ErrorCode.BIZ_ERROR_USER_NOT_LOGIN.msg());
        }

//TODO 权限验证
        /*String token = getUserToken(request);
        if (!token.equalsIgnoreCase("123456")) {
            //return "错误, 权限不合法!";
            //throw new MyBizException(ErrorCode.BIZ_ERROR_USER_NOT_LOGIN.value(),ErrorCode.BIZ_ERROR_USER_NOT_LOGIN.msg());
            return ResultUtil.error(new MyBizException(ErrorCode.BIZ_ERROR_USER_NOT_LOGIN.value(), ErrorCode.BIZ_ERROR_USER_NOT_LOGIN.msg()));
        }
*/
        //初始化请求头
        initHeaderContext(request);
        return joinPoint.proceed();
    }

    @After("pointcut()")
    public void after(JoinPoint jp) {
        RequestHeaderContext.clean();
        System.out.println("清理.....");
    }

    /**
     * 获取toke
     *
     * @param request
     * @return
     */
    private String getUserToken(HttpServletRequest request) {
        //TODO 线上需要获取cookies
        String token = request.getHeader(HEAD_TOKEN);

       /* Cookie[] cookies = request.getCookies();
        if (cookies == null) {
            return "";
        }
        for (Cookie cookie : cookies) {
            if (cookie.getName().equalsIgnoreCase("user_token")) {
                return cookie.getValue();
            }
        }*/
        return token;
    }

    private void initHeaderContext(HttpServletRequest request) {
        String token = request.getHeader(HEAD_TOKEN);
        //String userId = redisTemplate.get(token);
        new RequestHeaderContext.RequestHeaderContextBuild()
                .token(token)
                //.userId(userId)
                .bulid();

    }
    /**
     * 验证是否是debug状态
     *
     * @return
     */
    private boolean isDebug() {
        //TODO 上线回复注释
        boolean isDebug = java.lang.management.ManagementFactory.getRuntimeMXBean().
                getInputArguments().toString().indexOf("jdwp") >= 0;
        return isDebug;
    }

}
